package de.breitbeil.jbooking.task;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Locale;
import java.util.concurrent.ExecutionException;

import javax.swing.SwingWorker;

import org.springframework.context.MessageSource;
import org.springframework.richclient.application.Application;
import org.springframework.richclient.application.ApplicationServicesLocator;
import org.springframework.richclient.application.statusbar.StatusBar;
import org.springframework.richclient.application.statusbar.support.StatusBarProgressMonitor;
import org.springframework.richclient.progress.ProgressMonitor;

abstract public class AbstractTask<T, V> extends SwingWorker<T, V> {

    private ProgressMonitor progressMonitor;
    private String id;
    private MessageSource messageSource;
    private String messageTaskStarted;
    
    public AbstractTask(String id) {
        setId(id);
        
        StatusBar statusbar = Application.instance().getActiveWindow().getStatusBar();
        progressMonitor = statusbar.getProgressMonitor();
        addPropertyChangeListener( new ProgressBarUpdater() );
        
        messageSource = (MessageSource)ApplicationServicesLocator.services().getService(MessageSource.class);
        messageTaskStarted = getMessage(getId()+".taskStarted");
    }
    
    public boolean isUserCancelled() {
        return progressMonitor.isCanceled() || super.isCancelled();
    }
    
    public String getMessage(String code) {
        return messageSource.getMessage(code, null, Locale.getDefault());
    }
    
    public String getMessage(String code, Object[] args) {
        return messageSource.getMessage(code, args, Locale.getDefault());
    }
    
    @Override
    protected void done() {
        try {
            get();
        } catch (InterruptedException ignore) {
            // User has cancelled task
        } catch (ExecutionException e) {
            throw new RuntimeException(getMessage("taskexception.label"), e);
        } finally {
            progressMonitor.done();
        }
    }

    public int getTotalWork() {
        return StatusBarProgressMonitor.UNKNOWN;
    }
    
    public String getId() {
        return id;
    }
    
    public void setId(String id) {
        this.id = id;
    }
    
    protected class ProgressBarUpdater implements PropertyChangeListener {

        private final String progressProperty = "progress";
        private final String stateProperty = "state";
        
        public void propertyChange(PropertyChangeEvent evt) {
            String property = evt.getPropertyName();
            
            if(stateProperty.equals(property)) {
                StateValue newState = (StateValue) evt.getNewValue();
                if(newState == StateValue.STARTED) {
                    progressMonitor.taskStarted(messageTaskStarted, getTotalWork());
                }
                else if(newState == StateValue.DONE) {
                    progressMonitor.done();
                }
            }
            
            if( progressProperty.equals(property) ) {
                progressMonitor.worked((Integer)evt.getNewValue());
            }
        }
    }
    
}
